package com.ylr.gateway.framework.handler;

import com.ylr.base.common.exception.YlrException;
import com.ylr.base.common.tool.Result;
import com.alibaba.fastjson2.JSON;
import com.ylr.jwt.common.exception.CheckJwtException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2023-04-25 15:11:24
 * className: GatewayExceptionHandler gateway全局异常处理类
 * version: 1.0
 * description:
 *  网关异常处理器，优先级低于 ResponseStatusExceptionHandler 执行
 */
@Order(-1)
@Component
public class GatewayExceptionHandler implements ErrorWebExceptionHandler  {

    private static final Logger log = LoggerFactory.getLogger(GatewayExceptionHandler.class);

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        log.warn("Gateway Exception: url={} message={}", exchange.getRequest().getPath(), ex.getMessage(), ex);
        ServerHttpResponse response = exchange.getResponse();

        if (response.isCommitted()) {
            // 是否已提交
            log.warn("异常已提交");
            return Mono.error(ex);
        }

        Result<Object> result;
        response.setStatusCode(HttpStatus.OK);
        response.getHeaders().setContentType(MediaType.valueOf("application/json;charset=UTF-8"));
        if (ex instanceof ResponseStatusException) {
            log.debug("路由匹配不到服务，请求转发失败");
            result = Result.requestFail("很抱歉，您请求的服务不存在");
        } else if (ex instanceof UnsupportedOperationException) {
            log.error("服务宕机，请求转发失败");
            result = Result.fail("很抱歉，您请求的服务开小差了，请稍后重试");
        } else if (ex instanceof YlrException) {
            result = Result.getResult((YlrException) ex);
        } else if (ex instanceof CheckJwtException) {
            CheckJwtException checkJwtException = (CheckJwtException) ex;
            result = Result.getResult(checkJwtException.getCode(), checkJwtException.getMessage());
        } else {
            result = Result.fail();
        }

        return response.writeWith(Mono.just(response.bufferFactory().wrap(JSON.toJSONBytes(result))));
    }
}
